using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Extensions.Logging;

namespace DocumentCreationSystem.Services
{
    /// <summary>
    /// 工具调用性能监控器
    /// </summary>
    public class ToolCallPerformanceMonitor
    {
        private readonly ILogger _logger;
        private readonly ConcurrentDictionary<string, ToolCallMetrics> _toolMetrics;
        private readonly ConcurrentQueue<ToolCallRecord> _recentCalls;
        private const int MaxRecentCalls = 1000;

        public ToolCallPerformanceMonitor(ILogger logger)
        {
            _logger = logger;
            _toolMetrics = new ConcurrentDictionary<string, ToolCallMetrics>();
            _recentCalls = new ConcurrentQueue<ToolCallRecord>();
        }

        /// <summary>
        /// 记录工具调用开始
        /// </summary>
        public ToolCallSession StartToolCall(string toolName, string parameters)
        {
            return new ToolCallSession(this, toolName, parameters);
        }

        /// <summary>
        /// 记录工具调用完成
        /// </summary>
        internal void RecordToolCall(string toolName, string parameters, TimeSpan duration, bool success, string? errorMessage = null)
        {
            var record = new ToolCallRecord
            {
                ToolName = toolName,
                Parameters = parameters,
                Duration = duration,
                Success = success,
                ErrorMessage = errorMessage,
                Timestamp = DateTime.Now
            };

            // 添加到最近调用记录
            _recentCalls.Enqueue(record);
            while (_recentCalls.Count > MaxRecentCalls)
            {
                _recentCalls.TryDequeue(out _);
            }

            // 更新工具指标
            _toolMetrics.AddOrUpdate(toolName, 
                new ToolCallMetrics { ToolName = toolName },
                (key, existing) => existing.Update(record));

            // 记录日志
            if (success)
            {
                _logger.LogInformation($"工具调用成功: {toolName} 耗时 {duration.TotalMilliseconds:F2}ms");
            }
            else
            {
                _logger.LogWarning($"工具调用失败: {toolName} 耗时 {duration.TotalMilliseconds:F2}ms 错误: {errorMessage}");
            }
        }

        /// <summary>
        /// 获取工具性能统计
        /// </summary>
        public ToolCallStatistics GetStatistics()
        {
            var allRecords = _recentCalls.ToArray();
            var toolMetrics = _toolMetrics.Values.ToArray();

            return new ToolCallStatistics
            {
                TotalCalls = allRecords.Length,
                SuccessfulCalls = allRecords.Count(r => r.Success),
                FailedCalls = allRecords.Count(r => !r.Success),
                AverageResponseTime = allRecords.Any() ? TimeSpan.FromMilliseconds(allRecords.Average(r => r.Duration.TotalMilliseconds)) : TimeSpan.Zero,
                ToolMetrics = toolMetrics.ToDictionary(m => m.ToolName, m => m),
                RecentCalls = allRecords.OrderByDescending(r => r.Timestamp).Take(10).ToArray()
            };
        }

        /// <summary>
        /// 获取特定工具的性能指标
        /// </summary>
        public ToolCallMetrics? GetToolMetrics(string toolName)
        {
            return _toolMetrics.TryGetValue(toolName, out var metrics) ? metrics : null;
        }

        /// <summary>
        /// 获取性能报告
        /// </summary>
        public string GeneratePerformanceReport()
        {
            var stats = GetStatistics();
            var report = $@"
# 工具调用性能报告

## 总体统计
- 总调用次数: {stats.TotalCalls}
- 成功调用: {stats.SuccessfulCalls} ({(stats.TotalCalls > 0 ? (double)stats.SuccessfulCalls / stats.TotalCalls * 100 : 0):F1}%)
- 失败调用: {stats.FailedCalls} ({(stats.TotalCalls > 0 ? (double)stats.FailedCalls / stats.TotalCalls * 100 : 0):F1}%)
- 平均响应时间: {stats.AverageResponseTime.TotalMilliseconds:F2}ms

## 工具性能排行
";

            var topTools = stats.ToolMetrics.Values
                .OrderByDescending(m => m.CallCount)
                .Take(10);

            foreach (var tool in topTools)
            {
                report += $@"
### {tool.ToolName}
- 调用次数: {tool.CallCount}
- 成功率: {tool.SuccessRate:P1}
- 平均耗时: {tool.AverageResponseTime.TotalMilliseconds:F2}ms
- 最快: {tool.MinResponseTime.TotalMilliseconds:F2}ms
- 最慢: {tool.MaxResponseTime.TotalMilliseconds:F2}ms
";
            }

            return report;
        }

        /// <summary>
        /// 清除统计数据
        /// </summary>
        public void ClearStatistics()
        {
            _toolMetrics.Clear();
            while (_recentCalls.TryDequeue(out _)) { }
            _logger.LogInformation("工具调用统计数据已清除");
        }
    }

    /// <summary>
    /// 工具调用会话
    /// </summary>
    public class ToolCallSession : IDisposable
    {
        private readonly ToolCallPerformanceMonitor _monitor;
        private readonly string _toolName;
        private readonly string _parameters;
        private readonly Stopwatch _stopwatch;
        private bool _disposed = false;

        internal ToolCallSession(ToolCallPerformanceMonitor monitor, string toolName, string parameters)
        {
            _monitor = monitor;
            _toolName = toolName;
            _parameters = parameters;
            _stopwatch = Stopwatch.StartNew();
        }

        /// <summary>
        /// 标记调用成功完成
        /// </summary>
        public void MarkSuccess()
        {
            if (!_disposed)
            {
                _stopwatch.Stop();
                _monitor.RecordToolCall(_toolName, _parameters, _stopwatch.Elapsed, true);
                _disposed = true;
            }
        }

        /// <summary>
        /// 标记调用失败
        /// </summary>
        public void MarkFailure(string errorMessage)
        {
            if (!_disposed)
            {
                _stopwatch.Stop();
                _monitor.RecordToolCall(_toolName, _parameters, _stopwatch.Elapsed, false, errorMessage);
                _disposed = true;
            }
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _stopwatch.Stop();
                _monitor.RecordToolCall(_toolName, _parameters, _stopwatch.Elapsed, false, "未明确标记结果");
                _disposed = true;
            }
        }
    }

    /// <summary>
    /// 工具调用记录
    /// </summary>
    public class ToolCallRecord
    {
        public string ToolName { get; set; } = string.Empty;
        public string Parameters { get; set; } = string.Empty;
        public TimeSpan Duration { get; set; }
        public bool Success { get; set; }
        public string? ErrorMessage { get; set; }
        public DateTime Timestamp { get; set; }
    }

    /// <summary>
    /// 工具调用指标
    /// </summary>
    public class ToolCallMetrics
    {
        public string ToolName { get; set; } = string.Empty;
        public int CallCount { get; private set; }
        public int SuccessCount { get; private set; }
        public int FailureCount { get; private set; }
        public TimeSpan TotalResponseTime { get; private set; }
        public TimeSpan MinResponseTime { get; private set; } = TimeSpan.MaxValue;
        public TimeSpan MaxResponseTime { get; private set; } = TimeSpan.MinValue;

        public double SuccessRate => CallCount > 0 ? (double)SuccessCount / CallCount : 0;
        public TimeSpan AverageResponseTime => CallCount > 0 ? TimeSpan.FromTicks(TotalResponseTime.Ticks / CallCount) : TimeSpan.Zero;

        internal ToolCallMetrics Update(ToolCallRecord record)
        {
            CallCount++;
            if (record.Success)
                SuccessCount++;
            else
                FailureCount++;

            TotalResponseTime = TotalResponseTime.Add(record.Duration);
            
            if (record.Duration < MinResponseTime)
                MinResponseTime = record.Duration;
            
            if (record.Duration > MaxResponseTime)
                MaxResponseTime = record.Duration;

            return this;
        }
    }

    /// <summary>
    /// 工具调用统计信息
    /// </summary>
    public class ToolCallStatistics
    {
        public int TotalCalls { get; set; }
        public int SuccessfulCalls { get; set; }
        public int FailedCalls { get; set; }
        public TimeSpan AverageResponseTime { get; set; }
        public Dictionary<string, ToolCallMetrics> ToolMetrics { get; set; } = new();
        public ToolCallRecord[] RecentCalls { get; set; } = Array.Empty<ToolCallRecord>();
    }
}
